home *** CD-ROM | disk | FTP | other *** search
- /* Rendition.c by Martin Boyd 25-Apr-93.
- *
- * An example file loader using the OpalVision LSI interface.
- *
- * The rendition file format simply consists of a 1024 byte
- * header (Described below) followed by 32 bit (RGBA) image data
- * compressed using run-length encoding. Each run is encoded as
- * 6 bytes:
- *
- * Byte 0 - Red
- * Byte 1 - Green
- * Byte 2 - Blue
- * Byte 3 - Alpha
- * Byte 4 - Run length low byte
- * Byte 5 - Run length high byte
- *
- * NOTE: This loader only loads the 6RN format as described
- * above.
- */
-
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <opal/loadsave.h>
- #include <opal/opalpaint.h>
- #include <opal/opallib.h>
- #include <stdlib.h>
- #include <string.h>
-
-
- char Version[] = "\0$VER: Rendition.Loader 1.0 (25.04.93)";
-
- /* Rendition format information */
-
- struct Tile
- { long Ptr;
- long Length;
- };
-
- struct RendHeader /* 1024 byte header */
- { long Magic; /* H_MAGIC */
- SHORT Version; /* 2 */
- char Label[128]; /* ASCII Desciption */
- char Date[26]; /* Date of image creation */
- SHORT Height; /* Pixel height of image */
- SHORT Width; /* Pixel width of image */
- SHORT TileHeight; /* Pixel height of tile */
- SHORT TileWidth; /* Pixel width of tile */
- SHORT Format; /* See below */
- SHORT Encoding; /* See below */
- long NumRuns; /* Number of runs */
- SHORT BlockSize; /* 1024 */
- SHORT XOffset; /* Horizontal offset */
- SHORT YOffset; /* Vertical offset */
- long CMapLen; /* Number of colour table entries */
- long CMapPtr; /* Pointer to ColourMap */
- char CMapName[64]; /* Colour Map filename */
- struct Tile Tile[64]; /* Tile pointer table */
- char UnSpec[258]; /* Unspecified (reserved) */
- };
-
-
- #define H_MAGIC 0xE880
- #define H_BLOCKSIZE 1024
- #define H_HEADERSIZE 1024
-
- /* Format types */
- #define H_CRGBAPIX 2 /* 4 bytes per pixel */
- #define H_6RUNLH 11 /* 6 bytes per run */
- #define H_2RUN 12 /* 2 bytes per run; colour map in seperate file */
- #define H_2RUNMAP 13 /* 2 bytes per run; colour map in image file */
- #define H_COLOURMAP 20 /* 4 bytes per entry */
- #define H_MIPMAP 22 /* Mip map: header, map table and 4-byte pixels */
- #define H_ONEDRGBA8 23 /* 1D table of 4-byte pixels */
- #define H_ONEDBYTE 24 /* 1D table of bytes */
-
-
- char LoaderName[] = "Rendition";
- char PortName[] = "Rendition_Loader";
-
-
- int Width,Height; /* Dimension of the image being loaded */
- BPTR File; /* File handle of image being loaded */
- ULONG LoadFlags; /* Flags from the OVCMD_LOADIMAGE command */
- struct MsgPort *LoadPort; /* This modules message port */
- struct OpalBase *OpalBase;
-
- BOOL Do_Load (void);
-
-
- void main (void)
- {
- struct LSIMessage *Mesg;
- struct RendHeader *Header;
-
- LoadPort = CreatePort (PortName,0);
- if (LoadPort==NULL)
- exit (10);
- OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
- if (OpalBase==NULL)
- { DeletePort (LoadPort);
- exit (10);
- }
-
- if (!AddOVLoader (LoaderName,LoadPort,
- OVLF_ALLOWIMAGE|OVLF_ALLOWALPHA|OVLF_NEEDFILENAME))
- { DeletePort (LoadPort);
- CloseLibrary ((struct Library *)OpalBase);
- exit (10);
- }
- CloseLibrary ((struct Library *)OpalBase); /* library must be closed */
- OpalBase = NULL;
-
- while (1)
- { WaitPort (LoadPort);
- while (Mesg = (struct LSIMessage *)GetMsg (LoadPort))
- { switch (Mesg->lsi_Type)
- { case OVCMD_LOADIMAGE:
- File = Mesg->lsi_File;
- LoadFlags = Mesg->lsi_Flags;
- ReplyMsg ((struct Message *)Mesg);
- Do_Load();
- break;
- case OVCMD_EXPUNGE:
- if (!OpalBase)
- OpalBase = (struct OpalBase *)
- OpenLibrary ("opal.library",0);
- RemOVLoader (LoaderName);
- if (OpalBase)
- CloseLibrary ((struct Library *)OpalBase);
- DeletePort (LoadPort);
- ReplyMsg ((struct Message *)Mesg);
- exit (0);
- break;
- case OVCMD_FORMATCHECK:
- Header = (struct RendHeader *)Mesg->lsi_Address;
- if ((Header->Magic!=H_MAGIC) ||
- (Header->Format!=H_6RUNLH))
- Mesg->lsi_Result = FALSE;
- else
- { Width = Header->Width;
- Height = Header->Height;
- Mesg->lsi_Result = TRUE;
- Mesg->lsi_Width = Width;
- Mesg->lsi_Height = Height;
- Mesg->lsi_Depth = 24;
- Mesg->lsi_Flags = LSIF_HASIMAGE|LSIF_HASALPHA;
- }
- ReplyMsg ((struct Message *)Mesg);
- break;
- }
- }
- }
- }
-
-
-
- BOOL Do_Load (void)
- {
- int x,y;
- struct MsgPort *HostPort;
- struct LSIMessage Mesg;
- UBYTE *RBuff,*GBuff,*BBuff,*ABuff,*DestBuff,*SrcBuff;
- register UBYTE *Src,*R,*G,*B,*A,RData,GData,BData,AData;
- long SBuffSize,DBuffSize,FileLength,RunLength,AmountLeft;
- long AmountRead,FilePos;
- int DBuffRows,Row;
-
-
- HostPort = FindPort (OVLOADERPORT); /* Find the host port */
- if (HostPort==NULL) return (FALSE);
-
- memset (&Mesg,0,sizeof(struct LSIMessage));
- Mesg.lsi_Node.mn_Node.ln_Type = NT_MESSAGE;
- Mesg.lsi_Node.mn_ReplyPort = LoadPort;
- Mesg.lsi_Node.mn_Length = sizeof (struct LSIMessage);
-
- /* This buffer is used to hold the decompressed data */
- DBuffRows = 20;
- do
- { DBuffSize = DBuffRows * Width * 4;
- DestBuff = AllocMem (DBuffSize,MEMF_CLEAR);
- if (DestBuff==NULL)
- DBuffRows--;
- } while ((DestBuff==NULL) && (DBuffRows>0));
-
- if (DBuffRows==0)
- { Mesg.lsi_Type = OVCMD_ERROR;
- Mesg.lsi_Result = LSI_ERR_OUTOFMEM;
- LSICmd (HostPort,LoadPort,&Mesg);
- return (FALSE);
- }
- RBuff = DestBuff;
- GBuff = DestBuff+(1*DBuffRows*Width);
- BBuff = DestBuff+(2*DBuffRows*Width);
- ABuff = DestBuff+(3*DBuffRows*Width);
-
- /* Allocate a buffer for raw file data.
- * Allocate the biggest buffer we can, start
- * with the size of the file and work our way down.
- */
- Seek (File,0,OFFSET_END);
- FileLength = Seek (File,sizeof(struct RendHeader),OFFSET_BEGINNING);
- SBuffSize = FileLength - sizeof (struct RendHeader);
-
- do
- { SrcBuff = AllocMem (SBuffSize,MEMF_CLEAR);
- if (SrcBuff==NULL)
- SBuffSize = SBuffSize/2;
- }
- while ((SrcBuff==NULL) && (SBuffSize>(DBuffSize+1024)));
-
- if (SrcBuff==NULL)
- { FreeMem (DestBuff,DBuffSize);
- Mesg.lsi_Type = OVCMD_ERROR;
- Mesg.lsi_Result = LSI_ERR_OUTOFMEM;
- LSICmd (HostPort,LoadPort,&Mesg);
- return (FALSE);
- }
-
- /* Read in Image data and get the first run */
- FilePos = Seek (File,0,OFFSET_CURRENT);
- AmountRead = Read (File,SrcBuff,SBuffSize);
- AmountLeft = AmountRead;
- R = RBuff;
- G = GBuff;
- B = BBuff;
- A = ABuff;
- Src = SrcBuff;
- RData = *Src++;
- GData = *Src++;
- BData = *Src++;
- AData = *Src++;
- RunLength = *Src++;
- RunLength += (*Src++)<<8;
- Row = 0;
- AmountLeft -=6;
-
- for (y=0; y<Height; y++)
- { for (x=0; x<Width;x++)
- { if (RunLength==0)
- { if ((AmountLeft<6) && (FilePos+AmountRead<FileLength))
- { FilePos += AmountRead-AmountLeft;
- Seek (File,FilePos,OFFSET_BEGINNING);
- AmountRead = Read (File,SrcBuff,SBuffSize);
- AmountLeft = AmountRead;
- Src = SrcBuff;
- }
- RData = *Src++;
- GData = *Src++;
- BData = *Src++;
- AData = *Src++;
- RunLength = *Src++;
- RunLength += (*Src++)<<8;
- AmountLeft -= 6;
- }
- *R++ = RData;
- *G++ = GData;
- *B++ = BData;
- *A++ = AData;
- RunLength--;
- }
- Row++;
-
- /* Once decompress buffer is full, send
- * image data to host.
- */
-
- if ((Row==DBuffRows) || (y==Height-1))
- { Mesg.lsi_Planes[0] = RBuff;
- Mesg.lsi_Planes[1] = GBuff;
- Mesg.lsi_Planes[2] = BBuff;
- Mesg.lsi_Width = Width;
- Mesg.lsi_Height = Row;
- Mesg.lsi_X = 0;
- Mesg.lsi_Y = y-Row+1;
- Mesg.lsi_Type = OVCMD_SENDDATA;
- Mesg.lsi_SubType = OVDF_RGB;
- LSICmd (HostPort,LoadPort,&Mesg);
-
- /* Send Alpha channel data if requested */
-
- if (LoadFlags & LSIF_ALPHA)
- { Mesg.lsi_Planes[0] = ABuff;
- Mesg.lsi_Width = Width;
- Mesg.lsi_Height = Row;
- Mesg.lsi_X = 0;
- Mesg.lsi_Y = y-Row+1;
- Mesg.lsi_Type = OVCMD_SENDDATA;
- Mesg.lsi_SubType = OVDF_ALPHA;
- LSICmd (HostPort,LoadPort,&Mesg);
- }
- Row = 0;
- R = RBuff;
- G = GBuff;
- B = BBuff;
- A = ABuff;
- }
-
- if ((y & 0xF)==0)
- { Mesg.lsi_Type = OVCMD_PERCENTAGE;
- Mesg.lsi_Address = "Rend ";
- Mesg.lsi_Result = (y*100)/Height;
- LSICmd (HostPort,LoadPort,&Mesg);
- }
- }
-
- Mesg.lsi_Type = OVCMD_DONE;
- LSICmd (HostPort,LoadPort,&Mesg);
- FreeMem (DestBuff,DBuffSize);
- FreeMem (SrcBuff,SBuffSize);
- return (TRUE);
- }
-
-